Skip to content

fix(platform-objects): the zh-CN dashboard gap help text says what its source now says - #16163

Merged
zhuangjianguo merged 2 commits into
mainfrom
claude/issue-15511-zh-gap-helptext
Sep 6, 2026
Merged

fix(platform-objects): the zh-CN dashboard gap help text says what its source now says#16163
zhuangjianguo merged 2 commits into
mainfrom
claude/issue-15511-zh-gap-helptext

Conversation

@zhuangjianguo

@zhuangjianguo zhuangjianguo commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Fixes #15511

One leaf. metadataForms.dashboard.fields.gap.helpText in the zh-CN metadata-form bundle
was a faithful translation of a source sentence that no longer exists.

string
source, before objectstack#14586 Grid gap (Tailwind units)
source, now (packages/spec/src/ui/dashboard.form.ts:25) Space between widgets, in steps of 0.25rem (4 = 1rem)
zh-CN leaf, before this PR (:943) 「栅格间距(Tailwind 单位)」
zh-CN leaf, after this PR (:943) 「组件之间的间距,每级 0.25rem(4 = 1rem)」

Both strings were re-located by text, not by the line numbers triage recorded. The
English is unmoved and still reads exactly what triage quoted, at the same
dashboard.form.ts:25. The zh leaf has drifted from :935 to :943 as the bundle
grew, so the fix follows the text.

Why the wording

The new English does two things on purpose, and the replacement has to do both.

It drops the framework unit. "Tailwind units" names a CSS library the app author never
chose and cannot act on. So 「Tailwind 单位」 goes, and with it 「栅格间距」 — the English
stopped saying "Grid gap" too, and the author is spacing widgets, not addressing a grid.
The head clause is now 「组件之间的间距」: widgets is 「组件」 everywhere else in this
bundle (widgets.label, 「放置在栅格上的卡片与图表」, 「应用到所有组件的默认筛选与全局筛选」),
so the register matches the five sibling leaves this subtree had corrected on 2026-09-03.

It gains a magnitude. The dashboard renderer computes the gap as gap * 0.25rem, so
one step is exactly 0.25rem and the scale is linear — that is why the English kept
in steps of 0.25rem (4 = 1rem) rather than simplifying to a direction. A zh author who
only reads 「间距」 cannot size a dashboard; one who reads 「每级 0.25rem(4 = 1rem)」 can do
the same arithmetic the English reader does. 「每级 0.25rem」 renders "in steps of" as a
scale rather than a word-for-word calque, and the parenthetical carries the conversion by
example, which is what actually teaches it.

Two register choices, both measured against this bundle rather than picked:

  • = over 「即」. This bundle already spells an equivalence inside a full-width
    parenthetical as 「(留空 = 永久)」 — the same shape, an input value mapped to its meaning.
    Keeping = also preserves the source's equation exactly, which matters for a numeric
    conversion.
  • Full-width 「,」 and 「()」. Counted across every Chinese leaf in the file: 24
    full-width commas against 7 half-width, and all 7 half-width ones sit inside JSON or code
    literals where they belong; 79 full-width parens against 6, same split.

The head clause deliberately matches the objectui Studio overlay's own opening,
组件之间的间距 (objectui metadata-form-i18n.ts:90). objectui#7369 plans to delete that
overlay and consume this bundle instead, and objectui triage's reading on objectui#7673 was
that for a Chinese-reading audience, adding the magnitude beats deleting the overlay. This
string is what that convergence would land on, so it opens the way the overlay already
opens and adds precisely what the overlay lacks. Neither of those cards is touched here and
both remain open.

No instrument in this repo can see this

Re-run in this branch's worktree, exit codes captured by redirect-then-read, never through
a pipe:

                             BEFORE (stale leaf)   AFTER (this PR)
pnpm check:i18n                  exit 0                exit 0
  platform-objects               in sync (11 bundle(s))  in sync (11 bundle(s))
  OK (9 package(s) - all bundles in sync, no undeclared authoring keys)

pnpm check:i18n-stale-fill       exit 0                exit 0
  scanned 10 bundle set(s), 0 stale-fill leaf/leaves, 0 baselined

The numbers are identical either side of the change. That is the durable half of this
card: a green gate here is not evidence the change was needed, and not evidence it worked.

  • check:i18n compares committed bundles against a fresh extraction. Merge fills gaps
    only
    — the generated file's own header says so — and a present-but-stale leaf is not a
    gap, so --write rewrites the en leaf (a copy of the source, never merged) and leaves
    zh-CN alone. Regeneration is structurally incapable of fixing this.
  • check:i18n-stale-fill infers a stale fill from cross-locale agreement: it catches a
    leaf that is a copy of the English wearing a translation's name.
    「栅格间距(Tailwind 单位)」 was a real translation, written by a translator, agreeing with
    no other locale. It is invisible to that predicate by construction, not by accident.
  • There is no provenance to fall back on. zh-CN.source-hashes.generated.ts carries no
    dashboard entry at all
    — verified here, case-insensitively, real exit code 1 and zero
    matching lines, with a firing control on the same file (object matches 400 times). Per
    that file's own header, "a path with no entry is LEGACY-TRUSTED and never reported stale".

check:i18n initially returned exit 3 on the untouched tree — PREREQUISITE NOT MET,
the built CLI absent. That is not a red and not a green; the closure was built and the gate
re-run to a real verdict before any reading above was taken.

A fourth instrument, and it is blind too

The Docs Drift Check on this PR returned no opinion, and its stated reason lands on
this card. Re-run locally against the base commit
(node scripts/docs-audit/affected-docs.mjs --json 932acc3df), reading the fields rather
than the rendered comment:

docs:                []
anchors:             []
anchorlessChanges:   []
overbroadAnchors:    []
weakAnchorsDropped:  ["dashboard (symbol)"]

The name it could not anchor is dashboard, not gap. That distinction matters,
because the two are blind in different ways: dashboard WAS derived as an anchor candidate
and then dropped as a single lowercase word, while gap was never derived as a candidate
at all
anchors is empty and weakAnchorsDropped has exactly one entry. So no page
documenting this leaf can surface in that work list, by either route.

That makes four independent instruments structurally blind to this one stale string:
check:i18n, check:i18n-stale-fill, the provenance table, and the docs drift anchor
derivation. Not one of them is broken; each is answering a different question correctly, and
this defect falls between all four. That is the durable half of this card.

The hand pass the drift check could not do

Searched content/docs by hand for pages documenting the dashboard gap field by name or
by its help text, using the plain content/docs directory pathspec:

pattern files
Space between widgets 1
in steps of 0.25rem 1
0.25rem 1
Grid gap 0
Tailwind units 0
「栅格间距」 0
「Tailwind 单位」 0

Controls that fire, so the zeros are real zeros and not a pathspec or encoding artefact:
dashboard matches 76 files and refreshInterval 2 files under the same pathspec, and the
Chinese patterns are answerable there — 「的」 matches 4 files, so a Chinese fixed-string
search inside content/docs can return non-zero.

The single hit is content/docs/references/ui/dashboard.mdx:36, and it needs no change:

| **gap** | `integer` | optional | Space between widgets, in steps of 0.25rem (4 = 1rem) |

It already carries the current English, because that page is auto-generated from
packages/spec/src/ui/dashboard.zod.ts — the other producer objectstack#14586 rewrote — and
regenerates with it. The English documentation surface was never stale; only the translation
was. Nothing matched under content/docs/releases/ for any of the patterns above (0 for
all four English ones), so nothing in this PR goes near release notes.

Scope

One leaf, deliberately. columns is unchanged upstream so 「栅格列数(默认 12)」 stays
accurate, and the other five leaves of this subtree were corrected separately on 2026-09-03
— correctly leaving gap alone, because at that moment gap was still accurate. The
subtree was clean for one day. That is what makes this specimen worth its own card: it is
the first leaf of this class whose exact moment of going stale is known, a dated source edit
against a dated sweep that was right to skip it.

Cross-referenced with #14931 as its live worked example — that card is scoped to 613
legacy-trusted leaves of unknown provenance, and this one arrives by the other route. It is
a reference only: the two cards are not merged, #14931 stays open, and this PR is not
widened into its audit.

Filed separately rather than swept in here: the es-ES and ja-JP gap leaves carry the
same retired vocabulary from the same source edit.

Verification

  • Gate family derived from the diff, not judged: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
    → 47 families. All 47 green at c93760200, exit codes captured by redirect. Re-derived
    after the changeset landed; the family did not grow.
  • Two families first returned exit 3 (check:dual-build-cjs-loads,
    check:published-readme-exports) — PREREQUISITE NOT MET on packages with no dist/,
    none of them touched here. A full turbo run build cleared both and they are green in the
    union above.
  • pnpm --filter @objectstack/spec check:react-declaration-parity refuses locally with
    MANIFEST is not set; CI supplies that manifest from the objectui build
    (lint.yml:5496). Not a reading about this diff, which touches no file in packages/spec.
  • Contract surface: ablated against the base commit — every one of the 22 published
    declaration files byte-identical
    , with a firing control in the same run (6 published
    runtime files did move). Mutation proven on disk and in dist/ before measuring, restore
    proven after by blob equality against the HEAD blob plus an empty git diff HEAD.

The published movement is a string literal value inside the emitted zhCNMetadataForms
data structure. The leaf is typed as the declared metadataForms record member of
TranslationData (wrapped in NonNullable), so no literal type carries the text. No exported symbol, signature, or
accept/reject behaviour moves.

Changeset rather than the skip-changeset label: @objectstack/platform-objects is public
and publishes dist, and this string reaches a zh Studio author, so the diff does publish
something. patch, matching the sibling sweep's own changeset for the same subtree.

Authored by Claude Code session session_01ARYe3yQTQCUFm5qPYNgKaJ — attribution kept in
prose because a body edit downgrades the session-scoped footer link to the bare form.


Generated by Claude Code

…t its source moved out from under

`metadataForms.dashboard.fields.gap.helpText` read 「栅格间距(Tailwind 单位)」 — a
faithful translation of `Grid gap (Tailwind units)`, which the source no longer says.
`packages/spec/src/ui/dashboard.form.ts:25` now reads `Space between widgets, in steps
of 0.25rem (4 = 1rem)`: it dropped the framework unit an app author cannot act on and
gained a magnitude the author can compute with.

The leaf kept the retired vocabulary and never gained the magnitude, because bundle
merge fills gaps only — a present-but-stale leaf is not a gap. Now
「组件之间的间距,每级 0.25rem(4 = 1rem)」: `widgets` is 「组件」 as everywhere else in
this bundle, the grid framing is gone as it is upstream, and the conversion is carried
so a zh author can size `gap` without reading the English.

One leaf. `columns` is deliberately unchanged upstream, so 「栅格列数(默认 12)」 stays
accurate, and the rest of the subtree was corrected on 2026-09-03.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ
@github-actions github-actions Bot added the size/s label Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 2 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 658262e462bee93a4babcd93a1aeddd468097320packageMentionDocs.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tooling labels Sep 6, 2026
@zhuangjianguo
zhuangjianguo marked this pull request as ready for review September 6, 2026 04:13
@zhuangjianguo
zhuangjianguo added this pull request to the merge queue Sep 6, 2026
Merged via the queue into main with commit 021a735 Sep 6, 2026
38 checks passed
@zhuangjianguo
zhuangjianguo deleted the claude/issue-15511-zh-gap-helptext branch September 6, 2026 05:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tooling

Projects

None yet

2 participants